I. Simulation Preparations

Loading Libraries

# install.packages("plotly", dependencies=TRUE)
# install.packages("beepr")

library(readxl)
library(tidyverse)
library(ggplot2)
library(plotly)
library(hrbrthemes)
library(viridis)
library(stringr)
library(beepr)

Getting Input Data

path <- paste(getwd(),"/inputdata.xlsx", sep = "")

inputdata <- read_excel(path, sheet = "data")

Adding Columns for Initial Analysis

inputdata = cbind(inputdata,(100*inputdata$`Electricity Price`*inputdata$`Annual Electricity Consumption`)/inputdata$`Annual Income`, as.factor(round(inputdata$`Annual Income`,0)))
names(inputdata)[length(names(inputdata))-1]<-"RII"
names(inputdata)[length(names(inputdata))]<-"Income Category"

Understanding Current Energy Poverty Situation


inputdata %>%
  ggplot( aes(x=`Income Category`, y=RII, fill=`Income Category`)) +
  geom_boxplot() +
  scale_fill_viridis(discrete = TRUE, alpha=0.6, option="A") +
  theme(axis.text.x = element_text(size=10),
        legend.position="none",
        plot.title = element_text(size=11)
  ) +
  ggtitle("Ratio in Income (%) by Annual Income Group") +
  xlab("")+
  ylab("Electricity Budget Ratio in Income")+
  coord_flip()

Setting Simulation Input Columns

attach(inputdata)
h = `Number of Residents` # Number of residents in a household
i = `Annual Income` # Annual income of a household
c = `Annual Electricity Consumption` # Annual electricity consumption of a household
p = mean(`Electricity Price`) #Defining the electricity price of the selected region per KWh
m = `Statistical Multiplier` # Statistical multiplier for expressing how many households are represented by that survey

Checking Number of Simulation Cases

# Possible Free Electricity per Resident Cases
paste("EPR: from 0 to",trunc(sum(c * m) / sum(h * m)))

# Possible Free Electricity per Household Cases
paste("EPH: from 0 to",trunc(sum(c * m) / sum(m)))

# Total Number of Combinations to be Simulated
paste("Total Combinations (# of rows in million):",round(trunc(sum(c * m) / sum(h * m)) * trunc(sum(c * m) / sum(m)) /1000000, digits=1))

II. Simulation Implementation

EFRI Simulation Function

  • h: Household size (Number of residents) - list of numbers

  • i: Annual income of a household - list of numbers

  • c: Annual electricity consumption of a household - list of numbers

  • p: Electricity price - numeric input or list of numbers (same unit as income)

  • m: Statistical multiplier (number of represented households) - list of numbers

  • epov: Energy poverty threshold (% of income)

  • low : Income percentile threshold for selecting low income households

EFRI = function(h,i,c,p,m=1,epov=0.1,low=0.2,savename="EFRI_Sim")
 {
  
  start.time <- Sys.time()
  
  epr_limit = trunc(sum(c * m) / sum(h * m)) # Upper limit for free electricity  per resident (rounded down)
  eph_limit = trunc(sum(c * m) / sum(m)) # Upper limit for free electricity  per household (rounded down)
  
  datalist = list()
  counter = 1
  
  for(epr in 0:epr_limit)
  {
    for(eph in 0:eph_limit) # Computer RAM Consideration: Divide simulations if necessary (ex: 0:4500 and 4501:9000)
    {
      if(sum(epr*h*m)+sum(eph*m) > sum(c * m)) {
        next # EFRI Constraint: Total free electricity amount cannot be more than total consumed electricity in the population
      }
      rii_list = ((((sum((p*c)*m))/(sum((c-(pmin((epr*h+eph),c)))*m)))*((c-(pmin((epr*h+eph),c)))))/i)
      
      psim = sum((p*c)*m)/sum((c-(pmin((epr*h+eph),c)))*m)
      
      riiave = mean(rii_list) # Average Ratio in Income
      riiavelow = mean(rii_list[i<=quantile(i, probs=low)])
      
      riimed = median(rii_list) # Median Ratio in Income
      riimedlow = median(rii_list[i<=quantile(i, probs=low)])
      
      npr = sum(m[rii_list>=epov]*h[rii_list>=epov])
      nph = sum(m[rii_list>=epov])
      
      datalist [[counter]] = c(epr,eph,round(100*psim, digits = 2),round(100*riiave, digits = 2),round(100*riiavelow, digits = 2),round(100*riimed, digits = 2),round(100*riimedlow, digits = 2),round(npr, digits = 0),round(nph, digits = 0))
      counter = counter+1
    }
  }
  
  results = do.call(rbind, datalist)
  colnames(results) = c("EPR", "EPH","PSIM","RIIAVE","RIIAVELOW","RIIMED","RIIMEDLOW","NPR","NPH")
  
  EFRI_Sim <<- results
  
 
  csvpath <- paste(getwd(),"/", savename,".csv", sep = "")
  write.csv(EFRI_Sim, csvpath, row.names = FALSE)

  end.time <- Sys.time()
  time.taken <- end.time - start.time
  print(paste("* Simulation Duration: ", round(time.taken, digits = 2)), quote=FALSE)
  print(paste("** Simulation data is saved into ", savename, ".csv file at your current directory", sep = ""), quote=FALSE)

}

Running the Simulation


EFRI(h,i,c,p,m,epov=0.1)

beep(8) # Beep Sound when the simulation ends

III. Preparing Data for Visualization

Checking Simulation Results

savename = "EFRI_Sim"
rawpath <- paste(getwd(),"/", savename, ".csv", sep = "")
rawdata = read.csv(rawpath)

nrow(rawdata)

summary(rawdata)
beep(1)

Understanding Data Patterns

rawdata[5000:6000,] %>%
  ggplot(aes(x=NPR, y=PSIM)) + 
  geom_point() +
  xlab("Average Electricity Share in Low Income Budgets") +
  ylab("Price of Electricity")

Aggregating Data for Visualization

The raw simulation results include large number of rows. The patterns showed us that there are better combinations in terms of electricity price. For each objective (RIIAVE, RIIAVELOW, RIIMED, RIIMEDLOW, NPR, NPH) the combination with the minimum electricity price is taken with the same objective result.

The data can be aggregated in different ways. Here the Alternative 1 is selected and used for the visualizations.

Aggregation Alternative 1 : Sufficient Data
filter_ave    = aggregate(PSIM ~ RIIAVE,     data = rawdata, FUN = min)
filter_avelow = aggregate(PSIM ~ RIIAVELOW,  data = rawdata, FUN = min)
filter_med    = aggregate(PSIM ~ RIIMED,     data = rawdata, FUN = min)
filter_medlow = aggregate(PSIM ~ RIIMEDLOW,  data = rawdata, FUN = min)
filter_npr    = aggregate(PSIM ~ NPR,        data = rawdata, FUN = min)
filter_nph    = aggregate(PSIM ~ NPH,        data = rawdata, FUN = min)


agg_ave    = rawdata %>%
            filter(rawdata$PSIM == filter_ave$PSIM    | rawdata$RIIAVE    == filter_ave$RIIAVE)
agg_avelow = rawdata %>% 
            filter(rawdata$PSIM == filter_avelow$PSIM | rawdata$RIIAVELOW == filter_avelow$RIIAVELOW)
agg_med    = rawdata %>% 
            filter(rawdata$PSIM == filter_med$PSIM    | rawdata$RIIMED    == filter_med$RIIMED)
agg_medlow = rawdata %>% 
            filter(rawdata$PSIM == filter_medlow$PSIM | rawdata$RIIMEDLOW == filter_medlow$RIIMEDLOW)
agg_npr    = rawdata %>% 
            filter(rawdata$PSIM == filter_npr$PSIM    | rawdata$NPR       == filter_npr$NPR)
agg_nph    = rawdata %>% 
            filter(rawdata$PSIM == filter_nph$PSIM    | rawdata$NPH       == filter_nph$NPH)

simdata = rbind(agg_ave,agg_avelow,agg_med,agg_medlow,agg_npr,agg_nph) %>% distinct()

simpath = paste(getwd(),"/", savename, "_sim.csv", sep = "")
write.csv(simdata, simpath, row.names = FALSE)

rm(filter_ave, filter_avelow, filter_med, filter_medlow, filter_npr, filter_nph, agg_ave, agg_avelow, agg_med, agg_medlow, agg_npr, agg_nph)

beep(1)
Aggregation Alternative 2 : Less Data
filter_ave    = aggregate(PSIM ~ RIIAVE,     data = rawdata, FUN = min)
filter_avelow = aggregate(PSIM ~ RIIAVELOW,  data = rawdata, FUN = min)
filter_med    = aggregate(PSIM ~ RIIMED,     data = rawdata, FUN = min)
filter_medlow = aggregate(PSIM ~ RIIMEDLOW,  data = rawdata, FUN = min)
filter_npr    = aggregate(PSIM ~ NPR,        data = rawdata, FUN = min)
filter_nph    = aggregate(PSIM ~ NPH,        data = rawdata, FUN = min)

agg_ave    = semi_join(rawdata, filter_ave,    by=c("RIIAVE" = "RIIAVE",       "PSIM"="PSIM"))
agg_avelow = semi_join(rawdata, filter_avelow, by=c("RIIAVELOW" = "RIIAVELOW", "PSIM"="PSIM"))
agg_med    = semi_join(rawdata, filter_med,    by=c("RIIMED" = "RIIMED",       "PSIM"="PSIM"))
agg_medlow = semi_join(rawdata, filter_medlow, by=c("RIIMEDLOW" = "RIIMEDLOW", "PSIM"="PSIM"))
agg_npr    = semi_join(rawdata, filter_npr,    by=c("NPR" = "NPR",             "PSIM"="PSIM"))
agg_nph    = semi_join(rawdata, filter_nph,    by=c("NPH" = "NPH",             "PSIM"="PSIM"))

simdata = rbind(agg_ave,agg_avelow,agg_med,agg_medlow,agg_npr,agg_nph) %>% distinct()

simpath = paste(getwd(),"/", savename, "_sim.csv", sep = "")
write.csv(simdata, simpath, row.names = FALSE)

rm(filter_ave, filter_avelow, filter_med, filter_medlow, filter_npr, filter_nph, agg_ave, agg_avelow, agg_med, agg_medlow, agg_npr, agg_nph)

beep(1)
Aggregation Alternative 3 : More Data
filter_ave    = aggregate(PSIM ~ RIIAVE,     data = rawdata, FUN = min)
filter_avelow = aggregate(PSIM ~ RIIAVELOW,  data = rawdata, FUN = min)
filter_med    = aggregate(PSIM ~ RIIMED,     data = rawdata, FUN = min)
filter_medlow = aggregate(PSIM ~ RIIMEDLOW,  data = rawdata, FUN = min)
filter_npr    = aggregate(PSIM ~ NPR,        data = rawdata, FUN = min)
filter_nph    = aggregate(PSIM ~ NPH,        data = rawdata, FUN = min)

agg_ave    = semi_join(rawdata, filter_ave,    by=c("PSIM"="PSIM"))
agg_avelow = semi_join(rawdata, filter_avelow, by=c("PSIM"="PSIM"))
agg_med    = semi_join(rawdata, filter_med,    by=c("PSIM"="PSIM"))
agg_medlow = semi_join(rawdata, filter_medlow, by=c("PSIM"="PSIM"))
agg_npr    = semi_join(rawdata, filter_npr,    by=c("PSIM"="PSIM"))
agg_nph    = semi_join(rawdata, filter_nph,    by=c("PSIM"="PSIM"))

simdata = rbind(agg_ave,agg_avelow,agg_med,agg_medlow,agg_npr,agg_nph) %>% distinct()

simpath = paste(getwd(),"/", savename, "_sim.csv", sep = "")
write.csv(simdata, simpath, row.names = FALSE)

rm(filter_ave, filter_avelow, filter_med, filter_medlow, filter_npr, filter_nph, agg_ave, agg_avelow, agg_med, agg_medlow, agg_npr, agg_nph)

beep(1)

Defining the Optimum Points

normalizer <- function(x) {
  return ((x - min(x)) / (max(x) - min(x)))
}

opt_init   = rawdata[which(rawdata$EPR == 0 & rawdata$EPH ==0),]
opt_ave    = rawdata[which.min(sqrt(normalizer(rawdata$RIIAVE)   ^2 + normalizer(rawdata$PSIM)^2)),]
opt_avelow = rawdata[which.min(sqrt(normalizer(rawdata$RIIAVELOW)^2 + normalizer(rawdata$PSIM)^2)),]
opt_med    = rawdata[which.min(sqrt(normalizer(rawdata$RIIMED)   ^2 + normalizer(rawdata$PSIM)^2)),]
opt_medlow = rawdata[which.min(sqrt(normalizer(rawdata$RIIMEDLOW)^2 + normalizer(rawdata$PSIM)^2)),]
opt_npr    = rawdata[which.min(sqrt(normalizer(rawdata$NPR)      ^2 + normalizer(rawdata$PSIM)^2)),]
opt_nph    = rawdata[which.min(sqrt(normalizer(rawdata$NPH)      ^2 + normalizer(rawdata$PSIM)^2)),]

opt_init   = cbind(opt_init,   Simulation = "INITIAL")
opt_ave    = cbind(opt_ave,    Simulation = "RIIAVE")
opt_avelow = cbind(opt_avelow, Simulation = "RIIAVELOW")
opt_med    = cbind(opt_med,    Simulation = "RIIMED")
opt_medlow = cbind(opt_medlow, Simulation = "RIIMEDLOW")
opt_npr    = cbind(opt_npr,    Simulation = "NPR")
opt_nph    = cbind(opt_nph,    Simulation = "NPH")

optdata = rbind(opt_init, opt_ave,opt_avelow, opt_med, opt_medlow, opt_npr, opt_nph)

optpath = paste(getwd(),"/", savename, "_opt.csv", sep = "")
write.csv(optdata, optpath, row.names = FALSE)

rm(opt_init,opt_ave,opt_avelow,opt_med,opt_medlow,opt_npr,opt_nph,optpath)

beep(1)

IV. Simulated Data & Plots

Getting the Simulated Data

savename = "EFRI_Sim"
simpath = paste(getwd(),"/", savename, "_sim.csv", sep = "")
optpath = paste(getwd(),"/", savename, "_opt.csv", sep = "")

simdata = read.csv(simpath)
optdata = read.csv(optpath)

2D Plots

simdata %>%
  ggplot(aes(x=EPR, y=EPH, color=PSIM)) + 
  geom_point() +
  scale_color_gradient(low="gray", high="firebrick3") +
  xlab("Free Electricity per Resident") +
  ylab("Free Electricity per Household") +
  ggtitle("Free Electricity Amounts by Electricity Price")+
  geom_point(data=optdata[2:7,], 
             aes(x=EPR,y=EPH, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=EPR,y=EPH),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=EPR, y=EPH, color=NPH)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Free Electricity per Resident") +
  ylab("Free Electricity per Household") +
  ggtitle("Free Electricity Amounts by #EPOV Households")+
  geom_point(data=optdata[2:7,], 
             aes(x=EPR,y=EPH, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=EPR,y=EPH),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=EPR, y=EPH, color=NPR)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Free Electricity per Resident") +
  ylab("Free Electricity per Household") +
  ggtitle("Free Electricity Amounts by #EPOV Residents")+
  geom_point(data=optdata[2:7,], 
             aes(x=EPR,y=EPH, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=EPR,y=EPH),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=PSIM, y=RIIAVE, color=NPR)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Unit Price of Electricity") +
  ylab("Average Ratio in Income of All Households") +
  ggtitle("Average RII vs Electricity Price by #EPOV Residents")+
  geom_point(data=optdata[2:7,], 
             aes(x=PSIM,y=RIIAVE, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=PSIM,y=RIIAVE),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=PSIM, y=RIIAVELOW, color=NPR)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Unit Price of Electricity") +
  ylab("Average Ratio in Income of Low-Income Households") +
  ggtitle("Low-Income Average RII vs Electricity Price by #EPOV Residents")+
  geom_point(data=optdata[2:7,], 
             aes(x=PSIM,y=RIIAVELOW, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=PSIM,y=RIIAVELOW),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=PSIM, y=RIIMED, color=NPR)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Unit Price of Electricity") +
  ylab("Median Ratio in Income of All Households") +
  ggtitle("Median RII vs Electricity Price by #EPOV Residents")+
  geom_point(data=optdata[2:7,], 
             aes(x=PSIM,y=RIIMED, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=PSIM,y=RIIMED),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=PSIM, y=RIIMEDLOW, color=NPR)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Unit Price of Electricity") +
  ylab("Median Ratio in Income of Low-Income Households") +
  ggtitle("Low-Income Median RII vs Electricity Price by #EPOV Residents")+
  geom_point(data=optdata[2:7,], 
             aes(x=PSIM,y=RIIMEDLOW, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=PSIM,y=RIIMEDLOW),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=PSIM, y=NPH, color=NPH)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Unit Price of Electricity") +
  ylab("Number of Households Suffering From Energy Poverty") +
  ggtitle("#EPOV Households vs Electricity Price by #EPOV Households")+
  geom_point(data=optdata[2:7,], 
             aes(x=PSIM,y=NPH, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=PSIM,y=NPH),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=PSIM, y=NPR, color=NPR)) + 
  geom_point() +
  scale_color_gradient(low="turquoise", high="firebrick3") +
  xlab("Unit Price of Electricity") +
  ylab("Number of Residents Suffering From Energy Poverty") +
  ggtitle("#EPOV Residents vs Electricity Price by #EPOV Residents")+
  geom_point(data=optdata[2:7,], 
             aes(x=PSIM,y=NPR, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=PSIM,y=NPR),  
             color= "black", shape=1,
             size=3)

simdata %>%
  ggplot(aes(x=NPH, y=NPR, color=PSIM)) + 
  geom_point() +
  scale_color_gradient(low="gray", high="firebrick3") +
  xlab("Number of Households Suffering From Energy Poverty") +
  ylab("Number of Residents Suffering From Energy Poverty") +
  ggtitle("#EPOV Households vs #EPOV Residents by Electricity Price")+
  geom_point(data=optdata[2:7,], 
             aes(x=NPH,y=NPR, shape= Simulation), 
             color= "black", 
             size=3) +
  geom_point(data=optdata[1,], 
             aes(x=NPH,y=NPR),  
             color= "black", shape=1,
             size=3)

3D Plot

sim3d = plot_ly(simdata, x = ~EPR, y = ~EPH, z = ~PSIM,
                         marker = list(color = ~NPR, colorscale = c('#FFE1A1', '#683531'), showscale = TRUE))
sim3d = sim3d %>% add_markers()
sim3d = sim3d %>% layout(scene = list(xaxis = list(title = 'Free Electricity per Resident'),
                                             yaxis = list(title = 'Free Electricity per Household'),
                                             zaxis = list(title = 'Electricity Unit Price')),
                                annotations = list(
                                  x = 1.13,
                                  y = 1.05,
                                  text = '# People Suffering From EPOV',
                                  xref = 'paper',
                                  yref = 'paper',
                                  showarrow = FALSE
                                ))

sim3d

V. Initial vs Simulation Comparison

Selecting the Simulation Case for Comparison

The optimum cases are written into the optdata table with the following order:

  1. INITIAL: Initial case without granted free electricity

  2. RIIAVE: The case where the population average “ratio in income” is minimized

  3. RIIAVELOW: The case where the low-income average “ratio in income” is minimized

  4. RIIMED: The case where the population median“ratio in income” is minimized

  5. RIIMEDLOW: The case where the low-income median“ratio in income” is minimized

  6. NPR: The case where the number of residents with energy poverty is minimized

  7. NPH: The case where the number of households with energy poverty is minimized


case = 6 # NPR: The case that minimized number of residents with energy poverty

EPR = optdata[case,"EPR"]
EPH = optdata[case,"EPH"]
PRICEsim = optdata[case,"PSIM"]

EPR
[1] 982
EPH
[1] 0
PRICEsim
[1] 22.3

Adding Necessary Columns to the Initial Data Table

  • PRICEsim: New Electricity Price after providing free electricity

  • KWHgrant: Total Granted Free Electricity for a household

  • KWHgrcons: Consumed Amount of Free Electricity for a household

  • KWHpaid: Amount of Paid Electricity for the households where the free electricity amount is exceeded

  • RIIsim: New Ratio in Income for a household


comparisondata = cbind(inputdata,PRICEsim)
  names(comparisondata)[length(names(comparisondata))]<-"PRICEsim"

comparisondata = cbind(comparisondata,EPR*comparisondata$`Number of Residents` + EPH)
  names(comparisondata)[length(names(comparisondata))]<-"KWHgrant"
  
  comparisondata = cbind(comparisondata,pmin(comparisondata$KWHgrant,comparisondata$`Annual Electricity Consumption`))
 names(comparisondata)[length(names(comparisondata))]<-"KWHgrcons"
  
 comparisondata = cbind(comparisondata,comparisondata$`Annual Electricity Consumption` - comparisondata$KWHgrcons)
 names(comparisondata)[length(names(comparisondata))]<-"KWHpaid"

 comparisondata = cbind(comparisondata,(comparisondata$PRICEsim*comparisondata$KWHpaid)/comparisondata$`Annual Income`)
 names(comparisondata)[length(names(comparisondata))]<-"RIIsim"
 
 colnames(comparisondata)
 [1] "Electricity Price"              "Annual Electricity Consumption"
 [3] "Number of Residents"            "Annual Income"                 
 [5] "Statistical Multiplier"         "RII"                           
 [7] "Income Category"                "PRICEsim"                      
 [9] "KWHgrant"                       "KWHgrcons"                     
[11] "KWHpaid"                        "RIIsim"                        

Box-Plot of the Simulation Case

comparisondata %>%
   ggplot( aes(x=`Income Category`, y=RIIsim, fill=`Income Category`)) +
   geom_boxplot() +
   scale_fill_viridis(discrete = TRUE, alpha=0.6, option="A") +
   theme_get() +
   theme(axis.text.x = element_text(size=10),
         legend.position="none",
         plot.title = element_text(size=11)
   ) +
   ggtitle("Simulated Ratio in Income by Annual Income Group") +
   xlab("")+
   ylab("Electricity Budget Ratio in Income")+
   coord_flip()

Comparison of Each Income Level by Its Initial Situation

   a_ = comparisondata[,"Income Category"] %>% cbind(comparisondata[,"RII"], rep("Initial Case",nrow(comparisondata))) 
   b_ = comparisondata[,"Income Category"] %>% cbind(comparisondata[,"RIIsim"], rep("Simulated Case",nrow(comparisondata))) 
   
   comparisonplot = data.frame(rbind(a_,b_))
   comparisonplot[,2] = as.numeric(comparisonplot[,2])
   colnames(comparisonplot) = c("Group","RII","Case")
   
    comparisonplot %>%
     ggplot( aes(x=Group, y=RII, fill=Case)) +
     geom_boxplot() +
     facet_wrap(~Group, scale="free") +
     scale_fill_manual(values = c("grey", "turquoise")) +
     theme_get() +
     theme(axis.text.x = element_text(size=10),
           axis.text.y = element_blank(),
           legend.position=c(0.83,0.2),
           legend.title = element_blank(),
           legend.text = element_text(size=11),
           plot.title = element_text(size=12)
     ) +
    scale_shape_manual(values= c(1,19)) +
     ggtitle("Initial vs Simulated Ratio in Income by Income Groups") +
     xlab("")+
     ylab("Electricity Cost Ratio in Total Income of a Household")+
     coord_flip()

Reduction in the Number of Residents with Energy Poverty

1. Whole Population
EPOV_init = comparisondata %>% filter(RII>=10)
EPOV_init_total = sum(EPOV_init$`Statistical Multiplier`*EPOV_init$`Number of Residents`)

EPOV_sim = comparisondata %>% filter(RIIsim>=10)
EPOV_sim_total = sum(EPOV_sim$`Statistical Multiplier`*EPOV_sim$`Number of Residents`)

print("COMPARISON: Number of Total Energy Poor Residents")
[1] "COMPARISON: Number of Total Energy Poor Residents"
print(paste("Initial Case:",round(EPOV_init_total, digits=0)))
[1] "Initial Case: 3162044"
print(paste("Simulated Case:",round(EPOV_sim_total, digits=0)))
[1] "Simulated Case: 2475819"
print(paste("Difference (Number of Residents):",round(EPOV_init_total - EPOV_sim_total, digits=0)))
[1] "Difference (Number of Residents): 686225"
print(paste("Improvement (Number of Residents): %",100*round((EPOV_init_total - EPOV_sim_total)/EPOV_init_total, digits=4)))
[1] "Improvement (Number of Residents): % 21.7"
2. Low-Income Households

EPOV_init = LowIncome %>% filter(RII>=10)
EPOV_init_total = sum(EPOV_init$`Statistical Multiplier`*EPOV_init$`Number of Residents`)


EPOV_sim = LowIncome %>% filter(RIIsim>=10)
EPOV_sim_total = sum(EPOV_sim$`Statistical Multiplier`*EPOV_sim$`Number of Residents`)

print("COMPARISON: Number of Energy Poor Low-Income Residents")
[1] "COMPARISON: Number of Energy Poor Low-Income Residents"
print(paste("Initial Case:",round(EPOV_init_total, digits=0)))
[1] "Initial Case: 3055576"
print(paste("Simulated Case:",round(EPOV_sim_total, digits=0)))
[1] "Simulated Case: 2369351"
print(paste("Difference (Number of Residents):",round(EPOV_init_total - EPOV_sim_total, digits=0)))
[1] "Difference (Number of Residents): 686225"
print(paste("Improvement (Number of Residents): %",100*round((EPOV_init_total - EPOV_sim_total)/EPOV_init_total, digits=4)))
[1] "Improvement (Number of Residents): % 22.46"
LS0tDQp0aXRsZTogIkVuZXJneSBhcyBhIEZ1bmRhbWVudGFsIFJpZ2h0IH4gRUZSSSB+IFNpbXVsYXRpb24gTW9kZWwiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCiMgKipJLiBTaW11bGF0aW9uIFByZXBhcmF0aW9ucyoqDQoNCiMjIyAqKkxvYWRpbmcgTGlicmFyaWVzKioNCg0KYGBge3IgTGlicmFyeX0NCiMgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IiwgZGVwZW5kZW5jaWVzPVRSVUUpDQojIGluc3RhbGwucGFja2FnZXMoImJlZXByIikNCg0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShocmJydGhlbWVzKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShiZWVwcikNCmBgYA0KDQojIyMgKipHZXR0aW5nIElucHV0IERhdGEqKg0KDQpgYGB7ciBEYXRhIElucHV0fQ0KcGF0aCA8LSBwYXN0ZShnZXR3ZCgpLCIvaW5wdXRkYXRhLnhsc3giLCBzZXAgPSAiIikNCg0KaW5wdXRkYXRhIDwtIHJlYWRfZXhjZWwocGF0aCwgc2hlZXQgPSAiZGF0YSIpDQpgYGANCg0KIyMjICoqQWRkaW5nIENvbHVtbnMgZm9yIEluaXRpYWwgQW5hbHlzaXMqKg0KDQpgYGB7ciBJbml0aWFsIEFuYWx5c2lzfQ0KaW5wdXRkYXRhID0gY2JpbmQoaW5wdXRkYXRhLCgxMDAqaW5wdXRkYXRhJGBFbGVjdHJpY2l0eSBQcmljZWAqaW5wdXRkYXRhJGBBbm51YWwgRWxlY3RyaWNpdHkgQ29uc3VtcHRpb25gKS9pbnB1dGRhdGEkYEFubnVhbCBJbmNvbWVgLCBhcy5mYWN0b3Iocm91bmQoaW5wdXRkYXRhJGBBbm51YWwgSW5jb21lYCwwKSkpDQpuYW1lcyhpbnB1dGRhdGEpW2xlbmd0aChuYW1lcyhpbnB1dGRhdGEpKS0xXTwtIlJJSSINCm5hbWVzKGlucHV0ZGF0YSlbbGVuZ3RoKG5hbWVzKGlucHV0ZGF0YSkpXTwtIkluY29tZSBDYXRlZ29yeSINCmBgYA0KDQojIyMgKipVbmRlcnN0YW5kaW5nIEN1cnJlbnQgRW5lcmd5IFBvdmVydHkgU2l0dWF0aW9uKioNCg0KYGBge3IgUmVnaW9uIEJveFBsb3R9DQoNCmlucHV0ZGF0YSAlPiUNCiAgZ2dwbG90KCBhZXMoeD1gSW5jb21lIENhdGVnb3J5YCwgeT1SSUksIGZpbGw9YEluY29tZSBDYXRlZ29yeWApKSArDQogIGdlb21fYm94cGxvdCgpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgYWxwaGE9MC42LCBvcHRpb249IkEiKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICBsZWdlbmQucG9zaXRpb249Im5vbmUiLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTEpDQogICkgKw0KICBnZ3RpdGxlKCJSYXRpbyBpbiBJbmNvbWUgKCUpIGJ5IEFubnVhbCBJbmNvbWUgR3JvdXAiKSArDQogIHhsYWIoIiIpKw0KICB5bGFiKCJFbGVjdHJpY2l0eSBCdWRnZXQgUmF0aW8gaW4gSW5jb21lIikrDQogIGNvb3JkX2ZsaXAoKQ0KYGBgDQoNCiMjIyAqKlNldHRpbmcgU2ltdWxhdGlvbiBJbnB1dCBDb2x1bW5zKioNCg0KYGBge3IgRGl2aXNpb25zfQ0KYXR0YWNoKGlucHV0ZGF0YSkNCmggPSBgTnVtYmVyIG9mIFJlc2lkZW50c2AgIyBOdW1iZXIgb2YgcmVzaWRlbnRzIGluIGEgaG91c2Vob2xkDQppID0gYEFubnVhbCBJbmNvbWVgICMgQW5udWFsIGluY29tZSBvZiBhIGhvdXNlaG9sZA0KYyA9IGBBbm51YWwgRWxlY3RyaWNpdHkgQ29uc3VtcHRpb25gICMgQW5udWFsIGVsZWN0cmljaXR5IGNvbnN1bXB0aW9uIG9mIGEgaG91c2Vob2xkDQpwID0gbWVhbihgRWxlY3RyaWNpdHkgUHJpY2VgKSAjRGVmaW5pbmcgdGhlIGVsZWN0cmljaXR5IHByaWNlIG9mIHRoZSBzZWxlY3RlZCByZWdpb24gcGVyIEtXaA0KbSA9IGBTdGF0aXN0aWNhbCBNdWx0aXBsaWVyYCAjIFN0YXRpc3RpY2FsIG11bHRpcGxpZXIgZm9yIGV4cHJlc3NpbmcgaG93IG1hbnkgaG91c2Vob2xkcyBhcmUgcmVwcmVzZW50ZWQgYnkgdGhhdCBzdXJ2ZXkNCg0KYGBgDQoNCiMjIyAqKkNoZWNraW5nIE51bWJlciBvZiBTaW11bGF0aW9uIENhc2VzKioNCg0KYGBge3IgUkFNIENvbnNpZGVyYXRpb25zfQ0KIyBQb3NzaWJsZSBGcmVlIEVsZWN0cmljaXR5IHBlciBSZXNpZGVudCBDYXNlcw0KcGFzdGUoIkVQUjogZnJvbSAwIHRvIix0cnVuYyhzdW0oYyAqIG0pIC8gc3VtKGggKiBtKSkpDQoNCiMgUG9zc2libGUgRnJlZSBFbGVjdHJpY2l0eSBwZXIgSG91c2Vob2xkIENhc2VzDQpwYXN0ZSgiRVBIOiBmcm9tIDAgdG8iLHRydW5jKHN1bShjICogbSkgLyBzdW0obSkpKQ0KDQojIFRvdGFsIE51bWJlciBvZiBDb21iaW5hdGlvbnMgdG8gYmUgU2ltdWxhdGVkDQpwYXN0ZSgiVG90YWwgQ29tYmluYXRpb25zICgjIG9mIHJvd3MgaW4gbWlsbGlvbik6Iixyb3VuZCh0cnVuYyhzdW0oYyAqIG0pIC8gc3VtKGggKiBtKSkgKiB0cnVuYyhzdW0oYyAqIG0pIC8gc3VtKG0pKSAvMTAwMDAwMCwgZGlnaXRzPTEpKQ0KYGBgDQoNCiMgKipJSS4gU2ltdWxhdGlvbiBJbXBsZW1lbnRhdGlvbioqDQoNCiMjIyAqKkVGUkkgU2ltdWxhdGlvbiBGdW5jdGlvbioqDQoNCi0gICBoOiBIb3VzZWhvbGQgc2l6ZSAoTnVtYmVyIG9mIHJlc2lkZW50cykgLSBsaXN0IG9mIG51bWJlcnMNCg0KLSAgIGk6IEFubnVhbCBpbmNvbWUgb2YgYSBob3VzZWhvbGQgLSBsaXN0IG9mIG51bWJlcnMNCg0KLSAgIGM6IEFubnVhbCBlbGVjdHJpY2l0eSBjb25zdW1wdGlvbiBvZiBhIGhvdXNlaG9sZCAtIGxpc3Qgb2YgbnVtYmVycw0KDQotICAgcDogRWxlY3RyaWNpdHkgcHJpY2UgLSBudW1lcmljIGlucHV0IG9yIGxpc3Qgb2YgbnVtYmVycyAoc2FtZSB1bml0IGFzIGluY29tZSkNCg0KLSAgIG06IFN0YXRpc3RpY2FsIG11bHRpcGxpZXIgKG51bWJlciBvZiByZXByZXNlbnRlZCBob3VzZWhvbGRzKSAtIGxpc3Qgb2YgbnVtYmVycw0KDQotICAgZXBvdjogRW5lcmd5IHBvdmVydHkgdGhyZXNob2xkICglIG9mIGluY29tZSkNCg0KLSAgIGxvdyA6IEluY29tZSBwZXJjZW50aWxlIHRocmVzaG9sZCBmb3Igc2VsZWN0aW5nIGxvdyBpbmNvbWUgaG91c2Vob2xkcw0KDQpgYGB7ciBFRlJJIFNpbXVsYXRpb24gTW9kZWx9DQpFRlJJID0gZnVuY3Rpb24oaCxpLGMscCxtPTEsZXBvdj0wLjEsbG93PTAuMixzYXZlbmFtZT0iRUZSSV9TaW0iKQ0KIHsNCiAgDQogIHN0YXJ0LnRpbWUgPC0gU3lzLnRpbWUoKQ0KICANCiAgZXByX2xpbWl0ID0gdHJ1bmMoc3VtKGMgKiBtKSAvIHN1bShoICogbSkpICMgVXBwZXIgbGltaXQgZm9yIGZyZWUgZWxlY3RyaWNpdHkgIHBlciByZXNpZGVudCAocm91bmRlZCBkb3duKQ0KICBlcGhfbGltaXQgPSB0cnVuYyhzdW0oYyAqIG0pIC8gc3VtKG0pKSAjIFVwcGVyIGxpbWl0IGZvciBmcmVlIGVsZWN0cmljaXR5ICBwZXIgaG91c2Vob2xkIChyb3VuZGVkIGRvd24pDQogIA0KICBkYXRhbGlzdCA9IGxpc3QoKQ0KICBjb3VudGVyID0gMQ0KICANCiAgZm9yKGVwciBpbiAwOmVwcl9saW1pdCkNCiAgew0KICAgIGZvcihlcGggaW4gMDplcGhfbGltaXQpICMgQ29tcHV0ZXIgUkFNIENvbnNpZGVyYXRpb246IERpdmlkZSBzaW11bGF0aW9ucyBpZiBuZWNlc3NhcnkgKGV4OiAwOjQ1MDAgYW5kIDQ1MDE6OTAwMCkNCiAgICB7DQogICAgICBpZihzdW0oZXByKmgqbSkrc3VtKGVwaCptKSA+IHN1bShjICogbSkpIHsNCiAgICAgICAgbmV4dCAjIEVGUkkgQ29uc3RyYWludDogVG90YWwgZnJlZSBlbGVjdHJpY2l0eSBhbW91bnQgY2Fubm90IGJlIG1vcmUgdGhhbiB0b3RhbCBjb25zdW1lZCBlbGVjdHJpY2l0eSBpbiB0aGUgcG9wdWxhdGlvbg0KICAgICAgfQ0KICAgICAgcmlpX2xpc3QgPSAoKCgoc3VtKChwKmMpKm0pKS8oc3VtKChjLShwbWluKChlcHIqaCtlcGgpLGMpKSkqbSkpKSooKGMtKHBtaW4oKGVwcipoK2VwaCksYykpKSkpL2kpDQogICAgICANCiAgICAgIHBzaW0gPSBzdW0oKHAqYykqbSkvc3VtKChjLShwbWluKChlcHIqaCtlcGgpLGMpKSkqbSkNCiAgICAgIA0KICAgICAgcmlpYXZlID0gbWVhbihyaWlfbGlzdCkgIyBBdmVyYWdlIFJhdGlvIGluIEluY29tZQ0KICAgICAgcmlpYXZlbG93ID0gbWVhbihyaWlfbGlzdFtpPD1xdWFudGlsZShpLCBwcm9icz1sb3cpXSkNCiAgICAgIA0KICAgICAgcmlpbWVkID0gbWVkaWFuKHJpaV9saXN0KSAjIE1lZGlhbiBSYXRpbyBpbiBJbmNvbWUNCiAgICAgIHJpaW1lZGxvdyA9IG1lZGlhbihyaWlfbGlzdFtpPD1xdWFudGlsZShpLCBwcm9icz1sb3cpXSkNCiAgICAgIA0KICAgICAgbnByID0gc3VtKG1bcmlpX2xpc3Q+PWVwb3ZdKmhbcmlpX2xpc3Q+PWVwb3ZdKQ0KICAgICAgbnBoID0gc3VtKG1bcmlpX2xpc3Q+PWVwb3ZdKQ0KICAgICAgDQogICAgICBkYXRhbGlzdCBbW2NvdW50ZXJdXSA9IGMoZXByLGVwaCxyb3VuZCgxMDAqcHNpbSwgZGlnaXRzID0gMikscm91bmQoMTAwKnJpaWF2ZSwgZGlnaXRzID0gMikscm91bmQoMTAwKnJpaWF2ZWxvdywgZGlnaXRzID0gMikscm91bmQoMTAwKnJpaW1lZCwgZGlnaXRzID0gMikscm91bmQoMTAwKnJpaW1lZGxvdywgZGlnaXRzID0gMikscm91bmQobnByLCBkaWdpdHMgPSAwKSxyb3VuZChucGgsIGRpZ2l0cyA9IDApKQ0KICAgICAgY291bnRlciA9IGNvdW50ZXIrMQ0KICAgIH0NCiAgfQ0KICANCiAgcmVzdWx0cyA9IGRvLmNhbGwocmJpbmQsIGRhdGFsaXN0KQ0KICBjb2xuYW1lcyhyZXN1bHRzKSA9IGMoIkVQUiIsICJFUEgiLCJQU0lNIiwiUklJQVZFIiwiUklJQVZFTE9XIiwiUklJTUVEIiwiUklJTUVETE9XIiwiTlBSIiwiTlBIIikNCiAgDQogIEVGUklfU2ltIDw8LSByZXN1bHRzDQogIA0KIA0KICBjc3ZwYXRoIDwtIHBhc3RlKGdldHdkKCksIi8iLCBzYXZlbmFtZSwiLmNzdiIsIHNlcCA9ICIiKQ0KICB3cml0ZS5jc3YoRUZSSV9TaW0sIGNzdnBhdGgsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQogIGVuZC50aW1lIDwtIFN5cy50aW1lKCkNCiAgdGltZS50YWtlbiA8LSBlbmQudGltZSAtIHN0YXJ0LnRpbWUNCiAgcHJpbnQocGFzdGUoIiogU2ltdWxhdGlvbiBEdXJhdGlvbjogIiwgcm91bmQodGltZS50YWtlbiwgZGlnaXRzID0gMikpLCBxdW90ZT1GQUxTRSkNCiAgcHJpbnQocGFzdGUoIioqIFNpbXVsYXRpb24gZGF0YSBpcyBzYXZlZCBpbnRvICIsIHNhdmVuYW1lLCAiLmNzdiBmaWxlIGF0IHlvdXIgY3VycmVudCBkaXJlY3RvcnkiLCBzZXAgPSAiIiksIHF1b3RlPUZBTFNFKQ0KDQp9DQpgYGANCg0KIyMjICoqUnVubmluZyB0aGUgU2ltdWxhdGlvbioqDQoNCmBgYHtyIEVGUkkgUnVufQ0KDQpFRlJJKGgsaSxjLHAsbSxlcG92PTAuMSkNCg0KYmVlcCg4KSAjIEJlZXAgU291bmQgd2hlbiB0aGUgc2ltdWxhdGlvbiBlbmRzDQpgYGANCg0KIyAqKklJSS4gUHJlcGFyaW5nIERhdGEgZm9yIFZpc3VhbGl6YXRpb24qKg0KDQojIyMgKipDaGVja2luZyBTaW11bGF0aW9uIFJlc3VsdHMqKg0KDQpgYGB7ciBDaGVjayBSYXcgRGF0YX0NCnNhdmVuYW1lID0gIkVGUklfU2ltIg0KcmF3cGF0aCA8LSBwYXN0ZShnZXR3ZCgpLCIvIiwgc2F2ZW5hbWUsICIuY3N2Iiwgc2VwID0gIiIpDQpyYXdkYXRhID0gcmVhZC5jc3YocmF3cGF0aCkNCg0KbnJvdyhyYXdkYXRhKQ0KDQpzdW1tYXJ5KHJhd2RhdGEpDQpiZWVwKDEpDQpgYGANCg0KIyMjICoqVW5kZXJzdGFuZGluZyBEYXRhIFBhdHRlcm5zKioNCg0KYGBge3IgUmF3IERhdGEgUGF0dGVybnN9DQpyYXdkYXRhWzUwMDA6NjAwMCxdICU+JQ0KICBnZ3Bsb3QoYWVzKHg9TlBSLCB5PVBTSU0pKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICB4bGFiKCJBdmVyYWdlIEVsZWN0cmljaXR5IFNoYXJlIGluIExvdyBJbmNvbWUgQnVkZ2V0cyIpICsNCiAgeWxhYigiUHJpY2Ugb2YgRWxlY3RyaWNpdHkiKQ0KYGBgDQoNCiMjIyAqKkFnZ3JlZ2F0aW5nIERhdGEgZm9yIFZpc3VhbGl6YXRpb24qKg0KDQo+IFRoZSByYXcgc2ltdWxhdGlvbiByZXN1bHRzIGluY2x1ZGUgbGFyZ2UgbnVtYmVyIG9mIHJvd3MuIFRoZSBwYXR0ZXJucyBzaG93ZWQgdXMgdGhhdCB0aGVyZSBhcmUgYmV0dGVyIGNvbWJpbmF0aW9ucyBpbiB0ZXJtcyBvZiBlbGVjdHJpY2l0eSBwcmljZS4gRm9yIGVhY2ggb2JqZWN0aXZlIChSSUlBVkUsIFJJSUFWRUxPVywgUklJTUVELCBSSUlNRURMT1csIE5QUiwgTlBIKSB0aGUgY29tYmluYXRpb24gd2l0aCB0aGUgbWluaW11bSBlbGVjdHJpY2l0eSBwcmljZSBpcyB0YWtlbiB3aXRoIHRoZSBzYW1lIG9iamVjdGl2ZSByZXN1bHQuDQo+DQo+IFRoZSBkYXRhIGNhbiBiZSBhZ2dyZWdhdGVkIGluIGRpZmZlcmVudCB3YXlzLiBIZXJlIHRoZSAqKkFsdGVybmF0aXZlIDEqKiBpcyBzZWxlY3RlZCBhbmQgdXNlZCBmb3IgdGhlIHZpc3VhbGl6YXRpb25zLg0KDQojIyMjIyAqKkFnZ3JlZ2F0aW9uIEFsdGVybmF0aXZlIDEgOiBTdWZmaWNpZW50IERhdGEqKg0KDQpgYGB7ciBBZ2dyZWdhdGUgRGF0YX0NCmZpbHRlcl9hdmUgICAgPSBhZ2dyZWdhdGUoUFNJTSB+IFJJSUFWRSwgICAgIGRhdGEgPSByYXdkYXRhLCBGVU4gPSBtaW4pDQpmaWx0ZXJfYXZlbG93ID0gYWdncmVnYXRlKFBTSU0gfiBSSUlBVkVMT1csICBkYXRhID0gcmF3ZGF0YSwgRlVOID0gbWluKQ0KZmlsdGVyX21lZCAgICA9IGFnZ3JlZ2F0ZShQU0lNIH4gUklJTUVELCAgICAgZGF0YSA9IHJhd2RhdGEsIEZVTiA9IG1pbikNCmZpbHRlcl9tZWRsb3cgPSBhZ2dyZWdhdGUoUFNJTSB+IFJJSU1FRExPVywgIGRhdGEgPSByYXdkYXRhLCBGVU4gPSBtaW4pDQpmaWx0ZXJfbnByICAgID0gYWdncmVnYXRlKFBTSU0gfiBOUFIsICAgICAgICBkYXRhID0gcmF3ZGF0YSwgRlVOID0gbWluKQ0KZmlsdGVyX25waCAgICA9IGFnZ3JlZ2F0ZShQU0lNIH4gTlBILCAgICAgICAgZGF0YSA9IHJhd2RhdGEsIEZVTiA9IG1pbikNCg0KDQphZ2dfYXZlICAgID0gcmF3ZGF0YSAlPiUNCiAgICAgICAgICAgIGZpbHRlcihyYXdkYXRhJFBTSU0gPT0gZmlsdGVyX2F2ZSRQU0lNICAgIHwgcmF3ZGF0YSRSSUlBVkUgICAgPT0gZmlsdGVyX2F2ZSRSSUlBVkUpDQphZ2dfYXZlbG93ID0gcmF3ZGF0YSAlPiUgDQogICAgICAgICAgICBmaWx0ZXIocmF3ZGF0YSRQU0lNID09IGZpbHRlcl9hdmVsb3ckUFNJTSB8IHJhd2RhdGEkUklJQVZFTE9XID09IGZpbHRlcl9hdmVsb3ckUklJQVZFTE9XKQ0KYWdnX21lZCAgICA9IHJhd2RhdGEgJT4lIA0KICAgICAgICAgICAgZmlsdGVyKHJhd2RhdGEkUFNJTSA9PSBmaWx0ZXJfbWVkJFBTSU0gICAgfCByYXdkYXRhJFJJSU1FRCAgICA9PSBmaWx0ZXJfbWVkJFJJSU1FRCkNCmFnZ19tZWRsb3cgPSByYXdkYXRhICU+JSANCiAgICAgICAgICAgIGZpbHRlcihyYXdkYXRhJFBTSU0gPT0gZmlsdGVyX21lZGxvdyRQU0lNIHwgcmF3ZGF0YSRSSUlNRURMT1cgPT0gZmlsdGVyX21lZGxvdyRSSUlNRURMT1cpDQphZ2dfbnByICAgID0gcmF3ZGF0YSAlPiUgDQogICAgICAgICAgICBmaWx0ZXIocmF3ZGF0YSRQU0lNID09IGZpbHRlcl9ucHIkUFNJTSAgICB8IHJhd2RhdGEkTlBSICAgICAgID09IGZpbHRlcl9ucHIkTlBSKQ0KYWdnX25waCAgICA9IHJhd2RhdGEgJT4lIA0KICAgICAgICAgICAgZmlsdGVyKHJhd2RhdGEkUFNJTSA9PSBmaWx0ZXJfbnBoJFBTSU0gICAgfCByYXdkYXRhJE5QSCAgICAgICA9PSBmaWx0ZXJfbnBoJE5QSCkNCg0Kc2ltZGF0YSA9IHJiaW5kKGFnZ19hdmUsYWdnX2F2ZWxvdyxhZ2dfbWVkLGFnZ19tZWRsb3csYWdnX25wcixhZ2dfbnBoKSAlPiUgZGlzdGluY3QoKQ0KDQpzaW1wYXRoID0gcGFzdGUoZ2V0d2QoKSwiLyIsIHNhdmVuYW1lLCAiX3NpbS5jc3YiLCBzZXAgPSAiIikNCndyaXRlLmNzdihzaW1kYXRhLCBzaW1wYXRoLCByb3cubmFtZXMgPSBGQUxTRSkNCg0Kcm0oZmlsdGVyX2F2ZSwgZmlsdGVyX2F2ZWxvdywgZmlsdGVyX21lZCwgZmlsdGVyX21lZGxvdywgZmlsdGVyX25wciwgZmlsdGVyX25waCwgYWdnX2F2ZSwgYWdnX2F2ZWxvdywgYWdnX21lZCwgYWdnX21lZGxvdywgYWdnX25wciwgYWdnX25waCkNCg0KYmVlcCgxKQ0KYGBgDQoNCiMjIyMjICoqQWdncmVnYXRpb24gQWx0ZXJuYXRpdmUgMiA6IExlc3MgRGF0YSoqDQoNCmBgYCB7LlJ9DQpmaWx0ZXJfYXZlICAgID0gYWdncmVnYXRlKFBTSU0gfiBSSUlBVkUsICAgICBkYXRhID0gcmF3ZGF0YSwgRlVOID0gbWluKQ0KZmlsdGVyX2F2ZWxvdyA9IGFnZ3JlZ2F0ZShQU0lNIH4gUklJQVZFTE9XLCAgZGF0YSA9IHJhd2RhdGEsIEZVTiA9IG1pbikNCmZpbHRlcl9tZWQgICAgPSBhZ2dyZWdhdGUoUFNJTSB+IFJJSU1FRCwgICAgIGRhdGEgPSByYXdkYXRhLCBGVU4gPSBtaW4pDQpmaWx0ZXJfbWVkbG93ID0gYWdncmVnYXRlKFBTSU0gfiBSSUlNRURMT1csICBkYXRhID0gcmF3ZGF0YSwgRlVOID0gbWluKQ0KZmlsdGVyX25wciAgICA9IGFnZ3JlZ2F0ZShQU0lNIH4gTlBSLCAgICAgICAgZGF0YSA9IHJhd2RhdGEsIEZVTiA9IG1pbikNCmZpbHRlcl9ucGggICAgPSBhZ2dyZWdhdGUoUFNJTSB+IE5QSCwgICAgICAgIGRhdGEgPSByYXdkYXRhLCBGVU4gPSBtaW4pDQoNCmFnZ19hdmUgICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX2F2ZSwgICAgYnk9YygiUklJQVZFIiA9ICJSSUlBVkUiLCAgICAgICAiUFNJTSI9IlBTSU0iKSkNCmFnZ19hdmVsb3cgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX2F2ZWxvdywgYnk9YygiUklJQVZFTE9XIiA9ICJSSUlBVkVMT1ciLCAiUFNJTSI9IlBTSU0iKSkNCmFnZ19tZWQgICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX21lZCwgICAgYnk9YygiUklJTUVEIiA9ICJSSUlNRUQiLCAgICAgICAiUFNJTSI9IlBTSU0iKSkNCmFnZ19tZWRsb3cgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX21lZGxvdywgYnk9YygiUklJTUVETE9XIiA9ICJSSUlNRURMT1ciLCAiUFNJTSI9IlBTSU0iKSkNCmFnZ19ucHIgICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX25wciwgICAgYnk9YygiTlBSIiA9ICJOUFIiLCAgICAgICAgICAgICAiUFNJTSI9IlBTSU0iKSkNCmFnZ19ucGggICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX25waCwgICAgYnk9YygiTlBIIiA9ICJOUEgiLCAgICAgICAgICAgICAiUFNJTSI9IlBTSU0iKSkNCg0Kc2ltZGF0YSA9IHJiaW5kKGFnZ19hdmUsYWdnX2F2ZWxvdyxhZ2dfbWVkLGFnZ19tZWRsb3csYWdnX25wcixhZ2dfbnBoKSAlPiUgZGlzdGluY3QoKQ0KDQpzaW1wYXRoID0gcGFzdGUoZ2V0d2QoKSwiLyIsIHNhdmVuYW1lLCAiX3NpbS5jc3YiLCBzZXAgPSAiIikNCndyaXRlLmNzdihzaW1kYXRhLCBzaW1wYXRoLCByb3cubmFtZXMgPSBGQUxTRSkNCg0Kcm0oZmlsdGVyX2F2ZSwgZmlsdGVyX2F2ZWxvdywgZmlsdGVyX21lZCwgZmlsdGVyX21lZGxvdywgZmlsdGVyX25wciwgZmlsdGVyX25waCwgYWdnX2F2ZSwgYWdnX2F2ZWxvdywgYWdnX21lZCwgYWdnX21lZGxvdywgYWdnX25wciwgYWdnX25waCkNCg0KYmVlcCgxKQ0KYGBgDQoNCiMjIyMjICoqQWdncmVnYXRpb24gQWx0ZXJuYXRpdmUgMyA6IE1vcmUgRGF0YSoqDQoNCmBgYCB7LlJ9DQpmaWx0ZXJfYXZlICAgID0gYWdncmVnYXRlKFBTSU0gfiBSSUlBVkUsICAgICBkYXRhID0gcmF3ZGF0YSwgRlVOID0gbWluKQ0KZmlsdGVyX2F2ZWxvdyA9IGFnZ3JlZ2F0ZShQU0lNIH4gUklJQVZFTE9XLCAgZGF0YSA9IHJhd2RhdGEsIEZVTiA9IG1pbikNCmZpbHRlcl9tZWQgICAgPSBhZ2dyZWdhdGUoUFNJTSB+IFJJSU1FRCwgICAgIGRhdGEgPSByYXdkYXRhLCBGVU4gPSBtaW4pDQpmaWx0ZXJfbWVkbG93ID0gYWdncmVnYXRlKFBTSU0gfiBSSUlNRURMT1csICBkYXRhID0gcmF3ZGF0YSwgRlVOID0gbWluKQ0KZmlsdGVyX25wciAgICA9IGFnZ3JlZ2F0ZShQU0lNIH4gTlBSLCAgICAgICAgZGF0YSA9IHJhd2RhdGEsIEZVTiA9IG1pbikNCmZpbHRlcl9ucGggICAgPSBhZ2dyZWdhdGUoUFNJTSB+IE5QSCwgICAgICAgIGRhdGEgPSByYXdkYXRhLCBGVU4gPSBtaW4pDQoNCmFnZ19hdmUgICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX2F2ZSwgICAgYnk9YygiUFNJTSI9IlBTSU0iKSkNCmFnZ19hdmVsb3cgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX2F2ZWxvdywgYnk9YygiUFNJTSI9IlBTSU0iKSkNCmFnZ19tZWQgICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX21lZCwgICAgYnk9YygiUFNJTSI9IlBTSU0iKSkNCmFnZ19tZWRsb3cgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX21lZGxvdywgYnk9YygiUFNJTSI9IlBTSU0iKSkNCmFnZ19ucHIgICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX25wciwgICAgYnk9YygiUFNJTSI9IlBTSU0iKSkNCmFnZ19ucGggICAgPSBzZW1pX2pvaW4ocmF3ZGF0YSwgZmlsdGVyX25waCwgICAgYnk9YygiUFNJTSI9IlBTSU0iKSkNCg0Kc2ltZGF0YSA9IHJiaW5kKGFnZ19hdmUsYWdnX2F2ZWxvdyxhZ2dfbWVkLGFnZ19tZWRsb3csYWdnX25wcixhZ2dfbnBoKSAlPiUgZGlzdGluY3QoKQ0KDQpzaW1wYXRoID0gcGFzdGUoZ2V0d2QoKSwiLyIsIHNhdmVuYW1lLCAiX3NpbS5jc3YiLCBzZXAgPSAiIikNCndyaXRlLmNzdihzaW1kYXRhLCBzaW1wYXRoLCByb3cubmFtZXMgPSBGQUxTRSkNCg0Kcm0oZmlsdGVyX2F2ZSwgZmlsdGVyX2F2ZWxvdywgZmlsdGVyX21lZCwgZmlsdGVyX21lZGxvdywgZmlsdGVyX25wciwgZmlsdGVyX25waCwgYWdnX2F2ZSwgYWdnX2F2ZWxvdywgYWdnX21lZCwgYWdnX21lZGxvdywgYWdnX25wciwgYWdnX25waCkNCg0KYmVlcCgxKQ0KYGBgDQoNCiMjIyAqKkRlZmluaW5nIHRoZSBPcHRpbXVtIFBvaW50cyoqDQoNCmBgYHtyIE9wdGltdW0gUG9pbnRzfQ0Kbm9ybWFsaXplciA8LSBmdW5jdGlvbih4KSB7DQogIHJldHVybiAoKHggLSBtaW4oeCkpIC8gKG1heCh4KSAtIG1pbih4KSkpDQp9DQoNCm9wdF9pbml0ICAgPSByYXdkYXRhW3doaWNoKHJhd2RhdGEkRVBSID09IDAgJiByYXdkYXRhJEVQSCA9PTApLF0NCm9wdF9hdmUgICAgPSByYXdkYXRhW3doaWNoLm1pbihzcXJ0KG5vcm1hbGl6ZXIocmF3ZGF0YSRSSUlBVkUpICAgXjIgKyBub3JtYWxpemVyKHJhd2RhdGEkUFNJTSleMikpLF0NCm9wdF9hdmVsb3cgPSByYXdkYXRhW3doaWNoLm1pbihzcXJ0KG5vcm1hbGl6ZXIocmF3ZGF0YSRSSUlBVkVMT1cpXjIgKyBub3JtYWxpemVyKHJhd2RhdGEkUFNJTSleMikpLF0NCm9wdF9tZWQgICAgPSByYXdkYXRhW3doaWNoLm1pbihzcXJ0KG5vcm1hbGl6ZXIocmF3ZGF0YSRSSUlNRUQpICAgXjIgKyBub3JtYWxpemVyKHJhd2RhdGEkUFNJTSleMikpLF0NCm9wdF9tZWRsb3cgPSByYXdkYXRhW3doaWNoLm1pbihzcXJ0KG5vcm1hbGl6ZXIocmF3ZGF0YSRSSUlNRURMT1cpXjIgKyBub3JtYWxpemVyKHJhd2RhdGEkUFNJTSleMikpLF0NCm9wdF9ucHIgICAgPSByYXdkYXRhW3doaWNoLm1pbihzcXJ0KG5vcm1hbGl6ZXIocmF3ZGF0YSROUFIpICAgICAgXjIgKyBub3JtYWxpemVyKHJhd2RhdGEkUFNJTSleMikpLF0NCm9wdF9ucGggICAgPSByYXdkYXRhW3doaWNoLm1pbihzcXJ0KG5vcm1hbGl6ZXIocmF3ZGF0YSROUEgpICAgICAgXjIgKyBub3JtYWxpemVyKHJhd2RhdGEkUFNJTSleMikpLF0NCg0Kb3B0X2luaXQgICA9IGNiaW5kKG9wdF9pbml0LCAgIFNpbXVsYXRpb24gPSAiSU5JVElBTCIpDQpvcHRfYXZlICAgID0gY2JpbmQob3B0X2F2ZSwgICAgU2ltdWxhdGlvbiA9ICJSSUlBVkUiKQ0Kb3B0X2F2ZWxvdyA9IGNiaW5kKG9wdF9hdmVsb3csIFNpbXVsYXRpb24gPSAiUklJQVZFTE9XIikNCm9wdF9tZWQgICAgPSBjYmluZChvcHRfbWVkLCAgICBTaW11bGF0aW9uID0gIlJJSU1FRCIpDQpvcHRfbWVkbG93ID0gY2JpbmQob3B0X21lZGxvdywgU2ltdWxhdGlvbiA9ICJSSUlNRURMT1ciKQ0Kb3B0X25wciAgICA9IGNiaW5kKG9wdF9ucHIsICAgIFNpbXVsYXRpb24gPSAiTlBSIikNCm9wdF9ucGggICAgPSBjYmluZChvcHRfbnBoLCAgICBTaW11bGF0aW9uID0gIk5QSCIpDQoNCm9wdGRhdGEgPSByYmluZChvcHRfaW5pdCwgb3B0X2F2ZSxvcHRfYXZlbG93LCBvcHRfbWVkLCBvcHRfbWVkbG93LCBvcHRfbnByLCBvcHRfbnBoKQ0KDQpvcHRwYXRoID0gcGFzdGUoZ2V0d2QoKSwiLyIsIHNhdmVuYW1lLCAiX29wdC5jc3YiLCBzZXAgPSAiIikNCndyaXRlLmNzdihvcHRkYXRhLCBvcHRwYXRoLCByb3cubmFtZXMgPSBGQUxTRSkNCg0Kcm0ob3B0X2luaXQsb3B0X2F2ZSxvcHRfYXZlbG93LG9wdF9tZWQsb3B0X21lZGxvdyxvcHRfbnByLG9wdF9ucGgsb3B0cGF0aCkNCg0KYmVlcCgxKQ0KYGBgDQoNCiMgKipJVi4gU2ltdWxhdGVkIERhdGEgJiBQbG90cyoqDQoNCiMjIyAqKkdldHRpbmcgdGhlIFNpbXVsYXRlZCBEYXRhKioNCg0KYGBge3IgU2ltdWxhdGVkIERhdGF9DQpzYXZlbmFtZSA9ICJFRlJJX1NpbSINCnNpbXBhdGggPSBwYXN0ZShnZXR3ZCgpLCIvIiwgc2F2ZW5hbWUsICJfc2ltLmNzdiIsIHNlcCA9ICIiKQ0Kb3B0cGF0aCA9IHBhc3RlKGdldHdkKCksIi8iLCBzYXZlbmFtZSwgIl9vcHQuY3N2Iiwgc2VwID0gIiIpDQoNCnNpbWRhdGEgPSByZWFkLmNzdihzaW1wYXRoKQ0Kb3B0ZGF0YSA9IHJlYWQuY3N2KG9wdHBhdGgpDQpgYGANCg0KYGBge3IgUGxvdCAtIEVQUiB2cyBFUEggYnkgUHJpY2V9DQpzaW1kYXRhICU+JQ0KICBnZ3Bsb3QoYWVzKHg9RVBSLCB5PUVQSCwgY29sb3I9UFNJTSkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0iZ3JheSIsIGhpZ2g9ImZpcmVicmljazMiKSArDQogIHhsYWIoIkZyZWUgRWxlY3RyaWNpdHkgcGVyIFJlc2lkZW50IikgKw0KICB5bGFiKCJGcmVlIEVsZWN0cmljaXR5IHBlciBIb3VzZWhvbGQiKSArDQogIGdndGl0bGUoIkZyZWUgRWxlY3RyaWNpdHkgQW1vdW50cyBieSBFbGVjdHJpY2l0eSBQcmljZSIpKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsyOjcsXSwgDQogICAgICAgICAgICAgYWVzKHg9RVBSLHk9RVBILCBzaGFwZT0gU2ltdWxhdGlvbiksIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplPTMpICsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMSxdLCANCiAgICAgICAgICAgICBhZXMoeD1FUFIseT1FUEgpLCAgDQogICAgICAgICAgICAgY29sb3I9ICJibGFjayIsIHNoYXBlPTEsDQogICAgICAgICAgICAgc2l6ZT0zKQ0KYGBgDQoNCmBgYHtyIFBsb3QgLSBFUFIgdnMgRVBIIGJ5IE5QSH0NCnNpbWRhdGEgJT4lDQogIGdncGxvdChhZXMoeD1FUFIsIHk9RVBILCBjb2xvcj1OUEgpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9InR1cnF1b2lzZSIsIGhpZ2g9ImZpcmVicmljazMiKSArDQogIHhsYWIoIkZyZWUgRWxlY3RyaWNpdHkgcGVyIFJlc2lkZW50IikgKw0KICB5bGFiKCJGcmVlIEVsZWN0cmljaXR5IHBlciBIb3VzZWhvbGQiKSArDQogIGdndGl0bGUoIkZyZWUgRWxlY3RyaWNpdHkgQW1vdW50cyBieSAjRVBPViBIb3VzZWhvbGRzIikrDQogIGdlb21fcG9pbnQoZGF0YT1vcHRkYXRhWzI6NyxdLCANCiAgICAgICAgICAgICBhZXMoeD1FUFIseT1FUEgsIHNoYXBlPSBTaW11bGF0aW9uKSwgDQogICAgICAgICAgICAgY29sb3I9ICJibGFjayIsIA0KICAgICAgICAgICAgIHNpemU9MykgKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsxLF0sIA0KICAgICAgICAgICAgIGFlcyh4PUVQUix5PUVQSCksICANCiAgICAgICAgICAgICBjb2xvcj0gImJsYWNrIiwgc2hhcGU9MSwNCiAgICAgICAgICAgICBzaXplPTMpDQpgYGANCg0KYGBge3IgUGxvdCAtIEVQUiB2cyBFUEggYnkgTlBSfQ0Kc2ltZGF0YSAlPiUNCiAgZ2dwbG90KGFlcyh4PUVQUiwgeT1FUEgsIGNvbG9yPU5QUikpICsgDQogIGdlb21fcG9pbnQoKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0idHVycXVvaXNlIiwgaGlnaD0iZmlyZWJyaWNrMyIpICsNCiAgeGxhYigiRnJlZSBFbGVjdHJpY2l0eSBwZXIgUmVzaWRlbnQiKSArDQogIHlsYWIoIkZyZWUgRWxlY3RyaWNpdHkgcGVyIEhvdXNlaG9sZCIpICsNCiAgZ2d0aXRsZSgiRnJlZSBFbGVjdHJpY2l0eSBBbW91bnRzIGJ5ICNFUE9WIFJlc2lkZW50cyIpKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsyOjcsXSwgDQogICAgICAgICAgICAgYWVzKHg9RVBSLHk9RVBILCBzaGFwZT0gU2ltdWxhdGlvbiksIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplPTMpICsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMSxdLCANCiAgICAgICAgICAgICBhZXMoeD1FUFIseT1FUEgpLCAgDQogICAgICAgICAgICAgY29sb3I9ICJibGFjayIsIHNoYXBlPTEsDQogICAgICAgICAgICAgc2l6ZT0zKQ0KYGBgDQoNCmBgYHtyIFBsb3QgLSBQcmljZSB2cyBSSUlBVkV9DQpzaW1kYXRhICU+JQ0KICBnZ3Bsb3QoYWVzKHg9UFNJTSwgeT1SSUlBVkUsIGNvbG9yPU5QUikpICsgDQogIGdlb21fcG9pbnQoKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0idHVycXVvaXNlIiwgaGlnaD0iZmlyZWJyaWNrMyIpICsNCiAgeGxhYigiVW5pdCBQcmljZSBvZiBFbGVjdHJpY2l0eSIpICsNCiAgeWxhYigiQXZlcmFnZSBSYXRpbyBpbiBJbmNvbWUgb2YgQWxsIEhvdXNlaG9sZHMiKSArDQogIGdndGl0bGUoIkF2ZXJhZ2UgUklJIHZzIEVsZWN0cmljaXR5IFByaWNlIGJ5ICNFUE9WIFJlc2lkZW50cyIpKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsyOjcsXSwgDQogICAgICAgICAgICAgYWVzKHg9UFNJTSx5PVJJSUFWRSwgc2hhcGU9IFNpbXVsYXRpb24pLCANCiAgICAgICAgICAgICBjb2xvcj0gImJsYWNrIiwgDQogICAgICAgICAgICAgc2l6ZT0zKSArDQogIGdlb21fcG9pbnQoZGF0YT1vcHRkYXRhWzEsXSwgDQogICAgICAgICAgICAgYWVzKHg9UFNJTSx5PVJJSUFWRSksICANCiAgICAgICAgICAgICBjb2xvcj0gImJsYWNrIiwgc2hhcGU9MSwNCiAgICAgICAgICAgICBzaXplPTMpDQpgYGANCg0KYGBge3IgUGxvdCAtIFByaWNlIHZzIFJJSUFWRUxPV30NCnNpbWRhdGEgJT4lDQogIGdncGxvdChhZXMoeD1QU0lNLCB5PVJJSUFWRUxPVywgY29sb3I9TlBSKSkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93PSJ0dXJxdW9pc2UiLCBoaWdoPSJmaXJlYnJpY2szIikgKw0KICB4bGFiKCJVbml0IFByaWNlIG9mIEVsZWN0cmljaXR5IikgKw0KICB5bGFiKCJBdmVyYWdlIFJhdGlvIGluIEluY29tZSBvZiBMb3ctSW5jb21lIEhvdXNlaG9sZHMiKSArDQogIGdndGl0bGUoIkxvdy1JbmNvbWUgQXZlcmFnZSBSSUkgdnMgRWxlY3RyaWNpdHkgUHJpY2UgYnkgI0VQT1YgUmVzaWRlbnRzIikrDQogIGdlb21fcG9pbnQoZGF0YT1vcHRkYXRhWzI6NyxdLCANCiAgICAgICAgICAgICBhZXMoeD1QU0lNLHk9UklJQVZFTE9XLCBzaGFwZT0gU2ltdWxhdGlvbiksIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplPTMpICsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMSxdLCANCiAgICAgICAgICAgICBhZXMoeD1QU0lNLHk9UklJQVZFTE9XKSwgIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCBzaGFwZT0xLA0KICAgICAgICAgICAgIHNpemU9MykNCmBgYA0KDQpgYGB7ciBQbG90IC0gUHJpY2UgdnMgUklJTUVEfQ0Kc2ltZGF0YSAlPiUNCiAgZ2dwbG90KGFlcyh4PVBTSU0sIHk9UklJTUVELCBjb2xvcj1OUFIpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9InR1cnF1b2lzZSIsIGhpZ2g9ImZpcmVicmljazMiKSArDQogIHhsYWIoIlVuaXQgUHJpY2Ugb2YgRWxlY3RyaWNpdHkiKSArDQogIHlsYWIoIk1lZGlhbiBSYXRpbyBpbiBJbmNvbWUgb2YgQWxsIEhvdXNlaG9sZHMiKSArDQogIGdndGl0bGUoIk1lZGlhbiBSSUkgdnMgRWxlY3RyaWNpdHkgUHJpY2UgYnkgI0VQT1YgUmVzaWRlbnRzIikrDQogIGdlb21fcG9pbnQoZGF0YT1vcHRkYXRhWzI6NyxdLCANCiAgICAgICAgICAgICBhZXMoeD1QU0lNLHk9UklJTUVELCBzaGFwZT0gU2ltdWxhdGlvbiksIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplPTMpICsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMSxdLCANCiAgICAgICAgICAgICBhZXMoeD1QU0lNLHk9UklJTUVEKSwgIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCBzaGFwZT0xLA0KICAgICAgICAgICAgIHNpemU9MykNCmBgYA0KDQpgYGB7ciBQbG90IC0gUHJpY2UgdnMgUklJTUVETE9XfQ0Kc2ltZGF0YSAlPiUNCiAgZ2dwbG90KGFlcyh4PVBTSU0sIHk9UklJTUVETE9XLCBjb2xvcj1OUFIpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9InR1cnF1b2lzZSIsIGhpZ2g9ImZpcmVicmljazMiKSArDQogIHhsYWIoIlVuaXQgUHJpY2Ugb2YgRWxlY3RyaWNpdHkiKSArDQogIHlsYWIoIk1lZGlhbiBSYXRpbyBpbiBJbmNvbWUgb2YgTG93LUluY29tZSBIb3VzZWhvbGRzIikgKw0KICBnZ3RpdGxlKCJMb3ctSW5jb21lIE1lZGlhbiBSSUkgdnMgRWxlY3RyaWNpdHkgUHJpY2UgYnkgI0VQT1YgUmVzaWRlbnRzIikrDQogIGdlb21fcG9pbnQoZGF0YT1vcHRkYXRhWzI6NyxdLCANCiAgICAgICAgICAgICBhZXMoeD1QU0lNLHk9UklJTUVETE9XLCBzaGFwZT0gU2ltdWxhdGlvbiksIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplPTMpICsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMSxdLCANCiAgICAgICAgICAgICBhZXMoeD1QU0lNLHk9UklJTUVETE9XKSwgIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCBzaGFwZT0xLA0KICAgICAgICAgICAgIHNpemU9MykNCmBgYA0KDQpgYGB7ciBQbG90IC0gUHJpY2UgdnMgTlBIfQ0Kc2ltZGF0YSAlPiUNCiAgZ2dwbG90KGFlcyh4PVBTSU0sIHk9TlBILCBjb2xvcj1OUEgpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBzY2FsZV9jb2xvcl9ncmFkaWVudChsb3c9InR1cnF1b2lzZSIsIGhpZ2g9ImZpcmVicmljazMiKSArDQogIHhsYWIoIlVuaXQgUHJpY2Ugb2YgRWxlY3RyaWNpdHkiKSArDQogIHlsYWIoIk51bWJlciBvZiBIb3VzZWhvbGRzIFN1ZmZlcmluZyBGcm9tIEVuZXJneSBQb3ZlcnR5IikgKw0KICBnZ3RpdGxlKCIjRVBPViBIb3VzZWhvbGRzIHZzIEVsZWN0cmljaXR5IFByaWNlIGJ5ICNFUE9WIEhvdXNlaG9sZHMiKSsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMjo3LF0sIA0KICAgICAgICAgICAgIGFlcyh4PVBTSU0seT1OUEgsIHNoYXBlPSBTaW11bGF0aW9uKSwgDQogICAgICAgICAgICAgY29sb3I9ICJibGFjayIsIA0KICAgICAgICAgICAgIHNpemU9MykgKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsxLF0sIA0KICAgICAgICAgICAgIGFlcyh4PVBTSU0seT1OUEgpLCAgDQogICAgICAgICAgICAgY29sb3I9ICJibGFjayIsIHNoYXBlPTEsDQogICAgICAgICAgICAgc2l6ZT0zKQ0KYGBgDQoNCmBgYHtyIFBsb3QgLSBQcmljZSB2cyBOUFJ9DQpzaW1kYXRhICU+JQ0KICBnZ3Bsb3QoYWVzKHg9UFNJTSwgeT1OUFIsIGNvbG9yPU5QUikpICsgDQogIGdlb21fcG9pbnQoKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0idHVycXVvaXNlIiwgaGlnaD0iZmlyZWJyaWNrMyIpICsNCiAgeGxhYigiVW5pdCBQcmljZSBvZiBFbGVjdHJpY2l0eSIpICsNCiAgeWxhYigiTnVtYmVyIG9mIFJlc2lkZW50cyBTdWZmZXJpbmcgRnJvbSBFbmVyZ3kgUG92ZXJ0eSIpICsNCiAgZ2d0aXRsZSgiI0VQT1YgUmVzaWRlbnRzIHZzIEVsZWN0cmljaXR5IFByaWNlIGJ5ICNFUE9WIFJlc2lkZW50cyIpKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsyOjcsXSwgDQogICAgICAgICAgICAgYWVzKHg9UFNJTSx5PU5QUiwgc2hhcGU9IFNpbXVsYXRpb24pLCANCiAgICAgICAgICAgICBjb2xvcj0gImJsYWNrIiwgDQogICAgICAgICAgICAgc2l6ZT0zKSArDQogIGdlb21fcG9pbnQoZGF0YT1vcHRkYXRhWzEsXSwgDQogICAgICAgICAgICAgYWVzKHg9UFNJTSx5PU5QUiksICANCiAgICAgICAgICAgICBjb2xvcj0gImJsYWNrIiwgc2hhcGU9MSwNCiAgICAgICAgICAgICBzaXplPTMpDQpgYGANCg0KYGBge3IgUGxvdCAtIE5QSCB2cyBOUFJ9DQpzaW1kYXRhICU+JQ0KICBnZ3Bsb3QoYWVzKHg9TlBILCB5PU5QUiwgY29sb3I9UFNJTSkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIHNjYWxlX2NvbG9yX2dyYWRpZW50KGxvdz0iZ3JheSIsIGhpZ2g9ImZpcmVicmljazMiKSArDQogIHhsYWIoIk51bWJlciBvZiBIb3VzZWhvbGRzIFN1ZmZlcmluZyBGcm9tIEVuZXJneSBQb3ZlcnR5IikgKw0KICB5bGFiKCJOdW1iZXIgb2YgUmVzaWRlbnRzIFN1ZmZlcmluZyBGcm9tIEVuZXJneSBQb3ZlcnR5IikgKw0KICBnZ3RpdGxlKCIjRVBPViBIb3VzZWhvbGRzIHZzICNFUE9WIFJlc2lkZW50cyBieSBFbGVjdHJpY2l0eSBQcmljZSIpKw0KICBnZW9tX3BvaW50KGRhdGE9b3B0ZGF0YVsyOjcsXSwgDQogICAgICAgICAgICAgYWVzKHg9TlBILHk9TlBSLCBzaGFwZT0gU2ltdWxhdGlvbiksIA0KICAgICAgICAgICAgIGNvbG9yPSAiYmxhY2siLCANCiAgICAgICAgICAgICBzaXplPTMpICsNCiAgZ2VvbV9wb2ludChkYXRhPW9wdGRhdGFbMSxdLCANCiAgICAgICAgICAgICBhZXMoeD1OUEgseT1OUFIpLCAgDQogICAgICAgICAgICAgY29sb3I9ICJibGFjayIsIHNoYXBlPTEsDQogICAgICAgICAgICAgc2l6ZT0zKQ0KYGBgDQoNCmBgYHtyIDNEIFBsb3R9DQpzaW0zZCA9IHBsb3RfbHkoc2ltZGF0YSwgeCA9IH5FUFIsIHkgPSB+RVBILCB6ID0gflBTSU0sDQogICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VyID0gbGlzdChjb2xvciA9IH5OUFIsIGNvbG9yc2NhbGUgPSBjKCcjRkZFMUExJywgJyM2ODM1MzEnKSwgc2hvd3NjYWxlID0gVFJVRSkpDQpzaW0zZCA9IHNpbTNkICU+JSBhZGRfbWFya2VycygpDQpzaW0zZCA9IHNpbTNkICU+JSBsYXlvdXQoc2NlbmUgPSBsaXN0KHhheGlzID0gbGlzdCh0aXRsZSA9ICdGcmVlIEVsZWN0cmljaXR5IHBlciBSZXNpZGVudCcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ0ZyZWUgRWxlY3RyaWNpdHkgcGVyIEhvdXNlaG9sZCcpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gJ0VsZWN0cmljaXR5IFVuaXQgUHJpY2UnKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25zID0gbGlzdCgNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMS4xMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gMS4wNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gJyMgUGVvcGxlIFN1ZmZlcmluZyBGcm9tIEVQT1YnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhyZWYgPSAncGFwZXInLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlyZWYgPSAncGFwZXInLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dhcnJvdyA9IEZBTFNFDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQoNCnNpbTNkDQpgYGANCg0KIyAqKlYuIEluaXRpYWwgdnMgU2ltdWxhdGlvbiBDb21wYXJpc29uKioNCg0KIyMjICoqU2VsZWN0aW5nIHRoZSBTaW11bGF0aW9uIENhc2UgZm9yIENvbXBhcmlzb24qKg0KDQo+IFRoZSBvcHRpbXVtIGNhc2VzIGFyZSB3cml0dGVuIGludG8gdGhlICpvcHRkYXRhKiB0YWJsZSB3aXRoIHRoZSBmb2xsb3dpbmcgb3JkZXI6DQo+DQo+IDEuICAqKklOSVRJQUwqKjogSW5pdGlhbCBjYXNlICoqd2l0aG91dCBncmFudGVkIGZyZWUgZWxlY3RyaWNpdHkqKg0KPg0KPiAyLiAgKipSSUlBVkUqKjogVGhlIGNhc2Ugd2hlcmUgdGhlICoqcG9wdWxhdGlvbiBhdmVyYWdlICJyYXRpbyBpbiBpbmNvbWUiKiogaXMgbWluaW1pemVkDQo+DQo+IDMuICAqKlJJSUFWRUxPVyoqOiBUaGUgY2FzZSB3aGVyZSB0aGUgKipsb3ctaW5jb21lIGF2ZXJhZ2UgInJhdGlvIGluIGluY29tZSIqKiBpcyBtaW5pbWl6ZWQNCj4NCj4gNC4gICoqUklJTUVEKio6IFRoZSBjYXNlIHdoZXJlIHRoZSAqKnBvcHVsYXRpb24gbWVkaWFuInJhdGlvIGluIGluY29tZSIqKiBpcyBtaW5pbWl6ZWQNCj4NCj4gNS4gICoqUklJTUVETE9XKio6IFRoZSBjYXNlIHdoZXJlIHRoZSAqKmxvdy1pbmNvbWUgbWVkaWFuInJhdGlvIGluIGluY29tZSIqKiBpcyBtaW5pbWl6ZWQNCj4NCj4gNi4gICoqTlBSKio6IFRoZSBjYXNlIHdoZXJlIHRoZSBudW1iZXIgb2YgKipyZXNpZGVudHMgd2l0aCBlbmVyZ3kgcG92ZXJ0eSoqIGlzIG1pbmltaXplZA0KPg0KPiA3LiAgKipOUEgqKjogVGhlIGNhc2Ugd2hlcmUgdGhlIG51bWJlciBvZiAqKmhvdXNlaG9sZHMgd2l0aCBlbmVyZ3kgcG92ZXJ0eSoqIGlzIG1pbmltaXplZA0KDQpgYGB7ciBJbnB1dH0NCg0KY2FzZSA9IDYgIyBOUFI6IFRoZSBjYXNlIHRoYXQgbWluaW1pemVkIG51bWJlciBvZiByZXNpZGVudHMgd2l0aCBlbmVyZ3kgcG92ZXJ0eQ0KDQpFUFIgPSBvcHRkYXRhW2Nhc2UsIkVQUiJdDQpFUEggPSBvcHRkYXRhW2Nhc2UsIkVQSCJdDQpQUklDRXNpbSA9IG9wdGRhdGFbY2FzZSwiUFNJTSJdDQoNCkVQUiAjIEZyZWUgRWxlY3RyY2l0eSBwZXIgUmVzaWRlbnQNCkVQSCAjIEZyZWUgRWxlY3RyY2l0eSBwZXIgSG91c2Vob2xkDQpQUklDRXNpbSAjIE5ldyBFbGVjdHJpY2l0eSBQcmljZQ0KYGBgDQoNCiMjIyAqKkFkZGluZyBOZWNlc3NhcnkgQ29sdW1ucyB0byB0aGUgSW5pdGlhbCBEYXRhIFRhYmxlKioNCg0KPiAtICAgKipQUklDRXNpbSoqOiBOZXcgRWxlY3RyaWNpdHkgUHJpY2UgYWZ0ZXIgcHJvdmlkaW5nIGZyZWUgZWxlY3RyaWNpdHkNCj4NCj4gLSAgICoqS1dIZ3JhbnQqKjogVG90YWwgR3JhbnRlZCBGcmVlIEVsZWN0cmljaXR5IGZvciBhIGhvdXNlaG9sZA0KPg0KPiAtICAgKipLV0hncmNvbnMqKjogQ29uc3VtZWQgQW1vdW50IG9mIEZyZWUgRWxlY3RyaWNpdHkgZm9yIGEgaG91c2Vob2xkDQo+DQo+IC0gICAqKktXSHBhaWQqKjogQW1vdW50IG9mIFBhaWQgRWxlY3RyaWNpdHkgZm9yIHRoZSBob3VzZWhvbGRzIHdoZXJlIHRoZSBmcmVlIGVsZWN0cmljaXR5IGFtb3VudCBpcyBleGNlZWRlZA0KPg0KPiAtICAgKipSSUlzaW0qKjogTmV3IFJhdGlvIGluIEluY29tZSBmb3IgYSBob3VzZWhvbGQNCg0KYGBge3IgQ2JpbmRzfQ0KDQpjb21wYXJpc29uZGF0YSA9IGNiaW5kKGlucHV0ZGF0YSxQUklDRXNpbSkNCiAgbmFtZXMoY29tcGFyaXNvbmRhdGEpW2xlbmd0aChuYW1lcyhjb21wYXJpc29uZGF0YSkpXTwtIlBSSUNFc2ltIg0KDQpjb21wYXJpc29uZGF0YSA9IGNiaW5kKGNvbXBhcmlzb25kYXRhLEVQUipjb21wYXJpc29uZGF0YSRgTnVtYmVyIG9mIFJlc2lkZW50c2AgKyBFUEgpDQogIG5hbWVzKGNvbXBhcmlzb25kYXRhKVtsZW5ndGgobmFtZXMoY29tcGFyaXNvbmRhdGEpKV08LSJLV0hncmFudCINCiAgDQogIGNvbXBhcmlzb25kYXRhID0gY2JpbmQoY29tcGFyaXNvbmRhdGEscG1pbihjb21wYXJpc29uZGF0YSRLV0hncmFudCxjb21wYXJpc29uZGF0YSRgQW5udWFsIEVsZWN0cmljaXR5IENvbnN1bXB0aW9uYCkpDQogbmFtZXMoY29tcGFyaXNvbmRhdGEpW2xlbmd0aChuYW1lcyhjb21wYXJpc29uZGF0YSkpXTwtIktXSGdyY29ucyINCiAgDQogY29tcGFyaXNvbmRhdGEgPSBjYmluZChjb21wYXJpc29uZGF0YSxjb21wYXJpc29uZGF0YSRgQW5udWFsIEVsZWN0cmljaXR5IENvbnN1bXB0aW9uYCAtIGNvbXBhcmlzb25kYXRhJEtXSGdyY29ucykNCiBuYW1lcyhjb21wYXJpc29uZGF0YSlbbGVuZ3RoKG5hbWVzKGNvbXBhcmlzb25kYXRhKSldPC0iS1dIcGFpZCINCg0KIGNvbXBhcmlzb25kYXRhID0gY2JpbmQoY29tcGFyaXNvbmRhdGEsKGNvbXBhcmlzb25kYXRhJFBSSUNFc2ltKmNvbXBhcmlzb25kYXRhJEtXSHBhaWQpL2NvbXBhcmlzb25kYXRhJGBBbm51YWwgSW5jb21lYCkNCiBuYW1lcyhjb21wYXJpc29uZGF0YSlbbGVuZ3RoKG5hbWVzKGNvbXBhcmlzb25kYXRhKSldPC0iUklJc2ltIg0KIA0KIGNvbG5hbWVzKGNvbXBhcmlzb25kYXRhKQ0KYGBgDQoNCiMjIyAqKkJveC1QbG90IG9mIHRoZSBTaW11bGF0aW9uIENhc2UqKg0KDQpgYGB7ciBQbG90c30NCmNvbXBhcmlzb25kYXRhICU+JQ0KICAgZ2dwbG90KCBhZXMoeD1gSW5jb21lIENhdGVnb3J5YCwgeT1SSUlzaW0sIGZpbGw9YEluY29tZSBDYXRlZ29yeWApKSArDQogICBnZW9tX2JveHBsb3QoKSArDQogICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGUgPSBUUlVFLCBhbHBoYT0wLjYsIG9wdGlvbj0iQSIpICsNCiAgIHRoZW1lX2dldCgpICsNCiAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJub25lIiwNCiAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSkNCiAgICkgKw0KICAgZ2d0aXRsZSgiU2ltdWxhdGVkIFJhdGlvIGluIEluY29tZSBieSBBbm51YWwgSW5jb21lIEdyb3VwIikgKw0KICAgeGxhYigiIikrDQogICB5bGFiKCJFbGVjdHJpY2l0eSBCdWRnZXQgUmF0aW8gaW4gSW5jb21lIikrDQogICBjb29yZF9mbGlwKCkNCmBgYA0KDQojIyMgKipDb21wYXJpc29uIG9mIEVhY2ggSW5jb21lIExldmVsIGJ5IEl0cyBJbml0aWFsIFNpdHVhdGlvbioqDQoNCmBgYHtyIEluaXRpYWwgdnMgU2ltdWxhdGVkfQ0KICAgYV8gPSBjb21wYXJpc29uZGF0YVssIkluY29tZSBDYXRlZ29yeSJdICU+JSBjYmluZChjb21wYXJpc29uZGF0YVssIlJJSSJdLCByZXAoIkluaXRpYWwgQ2FzZSIsbnJvdyhjb21wYXJpc29uZGF0YSkpKSANCiAgIGJfID0gY29tcGFyaXNvbmRhdGFbLCJJbmNvbWUgQ2F0ZWdvcnkiXSAlPiUgY2JpbmQoY29tcGFyaXNvbmRhdGFbLCJSSUlzaW0iXSwgcmVwKCJTaW11bGF0ZWQgQ2FzZSIsbnJvdyhjb21wYXJpc29uZGF0YSkpKSANCiAgIA0KICAgY29tcGFyaXNvbnBsb3QgPSBkYXRhLmZyYW1lKHJiaW5kKGFfLGJfKSkNCiAgIGNvbXBhcmlzb25wbG90WywyXSA9IGFzLm51bWVyaWMoY29tcGFyaXNvbnBsb3RbLDJdKQ0KICAgY29sbmFtZXMoY29tcGFyaXNvbnBsb3QpID0gYygiR3JvdXAiLCJSSUkiLCJDYXNlIikNCiAgIA0KICAgIGNvbXBhcmlzb25wbG90ICU+JQ0KICAgICBnZ3Bsb3QoIGFlcyh4PUdyb3VwLCB5PVJJSSwgZmlsbD1DYXNlKSkgKw0KICAgICBnZW9tX2JveHBsb3QoKSArDQogICAgIGZhY2V0X3dyYXAofkdyb3VwLCBzY2FsZT0iZnJlZSIpICsNCiAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiZ3JleSIsICJ0dXJxdW9pc2UiKSkgKw0KICAgICB0aGVtZV9nZXQoKSArDQogICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uPWMoMC44MywwLjIpLA0KICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTEpLA0KICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpDQogICAgICkgKw0KICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9IGMoMSwxOSkpICsNCiAgICAgZ2d0aXRsZSgiSW5pdGlhbCB2cyBTaW11bGF0ZWQgUmF0aW8gaW4gSW5jb21lIGJ5IEluY29tZSBHcm91cHMiKSArDQogICAgIHhsYWIoIiIpKw0KICAgICB5bGFiKCJFbGVjdHJpY2l0eSBDb3N0IFJhdGlvIGluIFRvdGFsIEluY29tZSBvZiBhIEhvdXNlaG9sZCIpKw0KICAgICBjb29yZF9mbGlwKCkNCmBgYA0KDQojIyMgKipSZWR1Y3Rpb24gaW4gdGhlIE51bWJlciBvZiBSZXNpZGVudHMgd2l0aCBFbmVyZ3kgUG92ZXJ0eSoqDQoNCiMjIyMjICoqMS4gV2hvbGUgUG9wdWxhdGlvbioqDQoNCmBgYHtyICNFUE9WIFJlc2lkZW50c30NCkVQT1ZfaW5pdCA9IGNvbXBhcmlzb25kYXRhICU+JSBmaWx0ZXIoUklJPj0xMCkNCkVQT1ZfaW5pdF90b3RhbCA9IHN1bShFUE9WX2luaXQkYFN0YXRpc3RpY2FsIE11bHRpcGxpZXJgKkVQT1ZfaW5pdCRgTnVtYmVyIG9mIFJlc2lkZW50c2ApDQoNCkVQT1Zfc2ltID0gY29tcGFyaXNvbmRhdGEgJT4lIGZpbHRlcihSSUlzaW0+PTEwKQ0KRVBPVl9zaW1fdG90YWwgPSBzdW0oRVBPVl9zaW0kYFN0YXRpc3RpY2FsIE11bHRpcGxpZXJgKkVQT1Zfc2ltJGBOdW1iZXIgb2YgUmVzaWRlbnRzYCkNCg0KcHJpbnQoIkNPTVBBUklTT046IE51bWJlciBvZiBUb3RhbCBFbmVyZ3kgUG9vciBSZXNpZGVudHMiKQ0KDQpwcmludChwYXN0ZSgiSW5pdGlhbCBDYXNlOiIscm91bmQoRVBPVl9pbml0X3RvdGFsLCBkaWdpdHM9MCkpKQ0KcHJpbnQocGFzdGUoIlNpbXVsYXRlZCBDYXNlOiIscm91bmQoRVBPVl9zaW1fdG90YWwsIGRpZ2l0cz0wKSkpDQpwcmludChwYXN0ZSgiRGlmZmVyZW5jZSAoTnVtYmVyIG9mIFJlc2lkZW50cyk6Iixyb3VuZChFUE9WX2luaXRfdG90YWwgLSBFUE9WX3NpbV90b3RhbCwgZGlnaXRzPTApKSkNCnByaW50KHBhc3RlKCJJbXByb3ZlbWVudCAoTnVtYmVyIG9mIFJlc2lkZW50cyk6ICUiLDEwMCpyb3VuZCgoRVBPVl9pbml0X3RvdGFsIC0gRVBPVl9zaW1fdG90YWwpL0VQT1ZfaW5pdF90b3RhbCwgZGlnaXRzPTQpKSkNCmBgYA0KDQojIyMjIyAqKjIuIExvdy1JbmNvbWUgSG91c2Vob2xkcyoqDQoNCmBgYHtyICNFUE9WIExvdy1JbmNvbWUgUmVzaWRlbnRzfQ0KTG93SW5jb21lID0gY29tcGFyaXNvbmRhdGEgJT4lIGZpbHRlcihgQW5udWFsIEluY29tZWAgPD0gcXVhbnRpbGUoYEFubnVhbCBJbmNvbWVgLCBwcm9icz0wLjIpKQ0KICANCkVQT1ZfaW5pdCA9IExvd0luY29tZSAlPiUgZmlsdGVyKFJJST49MTApDQpFUE9WX2luaXRfdG90YWwgPSBzdW0oRVBPVl9pbml0JGBTdGF0aXN0aWNhbCBNdWx0aXBsaWVyYCpFUE9WX2luaXQkYE51bWJlciBvZiBSZXNpZGVudHNgKQ0KDQpFUE9WX3NpbSA9IExvd0luY29tZSAlPiUgZmlsdGVyKFJJSXNpbT49MTApDQpFUE9WX3NpbV90b3RhbCA9IHN1bShFUE9WX3NpbSRgU3RhdGlzdGljYWwgTXVsdGlwbGllcmAqRVBPVl9zaW0kYE51bWJlciBvZiBSZXNpZGVudHNgKQ0KDQpwcmludCgiQ09NUEFSSVNPTjogTnVtYmVyIG9mIEVuZXJneSBQb29yIExvdy1JbmNvbWUgUmVzaWRlbnRzIikNCg0KcHJpbnQocGFzdGUoIkluaXRpYWwgQ2FzZToiLHJvdW5kKEVQT1ZfaW5pdF90b3RhbCwgZGlnaXRzPTApKSkNCnByaW50KHBhc3RlKCJTaW11bGF0ZWQgQ2FzZToiLHJvdW5kKEVQT1Zfc2ltX3RvdGFsLCBkaWdpdHM9MCkpKQ0KcHJpbnQocGFzdGUoIkRpZmZlcmVuY2UgKE51bWJlciBvZiBSZXNpZGVudHMpOiIscm91bmQoRVBPVl9pbml0X3RvdGFsIC0gRVBPVl9zaW1fdG90YWwsIGRpZ2l0cz0wKSkpDQpwcmludChwYXN0ZSgiSW1wcm92ZW1lbnQgKE51bWJlciBvZiBSZXNpZGVudHMpOiAlIiwxMDAqcm91bmQoKEVQT1ZfaW5pdF90b3RhbCAtIEVQT1Zfc2ltX3RvdGFsKS9FUE9WX2luaXRfdG90YWwsIGRpZ2l0cz00KSkpDQpgYGANCg==